home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / mint / mgr / sparcmgr / src.zoo / src / graph_subs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-03-17  |  5.9 KB  |  266 lines

  1. /*                        Copyright (c) 1987 Bellcore
  2.  *                            All Rights Reserved
  3.  *       Permission is granted to copy or use this program, EXCEPT that it
  4.  *       may not be sold for profit, the copyright notice must be reproduced
  5.  *       on copies, and credit should be given to Bellcore where it is due.
  6.  *       BELLCORE MAKES NO WARRANTY AND ACCEPTS NO LIABILITY FOR THIS PROGRAM.
  7.  */
  8. /*    $Header: graph_subs.c,v 1.1 89/03/17 08:21:11 sau Exp $
  9.     $Source: /m1/mgr.new/src/RCS/graph_subs.c,v $
  10. */
  11. static char    RCSid_[] = "$Source: /m1/mgr.new/src/RCS/graph_subs.c,v $$Revision: 1.1 $";
  12.  
  13. /* graphics subs  - mostly from the BLIT */
  14.  
  15. #include "bitmap.h"
  16.  
  17. /* circle of radius r centered at x1,y1 */
  18.  
  19. circle(b,x1,y1,r,f)
  20. BITMAP  *b;
  21. int x1;
  22. register int y1;
  23. int r, f;
  24. {
  25.    register err = 0;        /* x^2 + y^2 - r^2 */
  26.    register dxsq = 1;        /* (x+dx)^2-x^2*/
  27.    register dysq = 1 - 2*r;
  28.    register exy;
  29.    int x0 = x1;
  30.    register y0 = y1 - r;
  31.  
  32.    y1 += r;
  33.    while(y1 > y0) {
  34.       bit_point(b,x0,y0,f);
  35.       bit_point(b,x0,y1,f);
  36.       bit_point(b,x1,y0,f);
  37.       bit_point(b,x1,y1,f);
  38.       exy = err + dxsq + dysq;
  39.       if(-exy <= err+dxsq) {
  40.          y1--;
  41.          y0++;
  42.          err += dysq;
  43.          dysq += 2;
  44.          }
  45.       if(exy <= -err) {
  46.          x1++;
  47.          x0--;
  48.          err += dxsq;
  49.          dxsq += 2;
  50.          }
  51.       }
  52.    bit_point(b,x0,y0,f);
  53.    bit_point(b,x1,y0,f);
  54.    }
  55.  
  56.  
  57. #define labs(x,y)        if((x=y)<0) x= -x
  58. #define    BIG            0x7fff
  59. #define    HUGE            0x3fffffffL
  60.  
  61. int bit_point();
  62.  
  63. /* draw an ellipse centered at x0,y0 with half-axes a,b */
  64.  
  65. ellipse(screen, x, y, a, b, f)
  66. BITMAP *screen;
  67. int x, y;
  68. int a, b;
  69. int f;
  70.    {
  71.    if(a==0 || b==0)
  72.       bit_line(screen, x-a, y-b, x+a, y+b, f);
  73.    else
  74.       ellip1(screen, x, y, a, b, bit_point, 0, b, 0, b, f);
  75.    }
  76.  
  77. /* calculate b*b*x*x + a*a*y*y - a*a*b*b avoiding ovfl */
  78.  
  79. static long
  80. resid(a,b,x,y)
  81. register a,b;
  82.    {
  83.    long result = 0;
  84.    long u = b*((long)a*a - (long)x*x);
  85.    long v = (long)a*y*y;
  86.    register q = u>BIG? HUGE/u: BIG;
  87.    register r = v>BIG? HUGE/v: BIG;
  88.    while(a || b) {
  89.       if(result>=0 && b) {
  90.          if(q>b) q = b;
  91.          result -= q*u;
  92.          b -= q;
  93.          }
  94.       else {
  95.          if(r>a) r = a;
  96.          result += r*v;
  97.          a -= r;
  98.          }
  99.       }
  100.    return(result);
  101.    }
  102.  
  103. /*
  104.  * clockwise ellipse centered at x0,y0 with half-axes a,b.
  105.  * from x1,y1 to x2,y2
  106.  * do "action" at each point
  107.  */
  108.  
  109. ellip1(screen, x0,y0, a, b, action, x1,y1, x2,y2, f)
  110. int x0,y0, x1,y1, x2, y2;
  111. register void (*action)();
  112. BITMAP *screen;
  113. int f;
  114.    {
  115.    int z;
  116.    int dx = y1>0? 1: y1<0? -1: x1>0? -1: 1;
  117.    int dy = x1>0? -1: x1<0? 1: y1>0? -1: 1;
  118.    long a2 = (long)a*a;
  119.    long b2 = (long)b*b;
  120.    register long dex = b2*(2*dx*x1+1);
  121.    register long e;
  122.    register long dey = a2*(2*dy*y1+1);
  123.    register long ex, ey, exy;
  124.  
  125.    e = resid(a, b, x1, y1);
  126.    a2 *= 2;
  127.    b2 *= 2;
  128.    do {
  129.       labs(ex, e+dex);
  130.       labs(ey, e+dey);
  131.       labs(exy, e+dex+dey);
  132.       if(exy<=ex || ey<ex) {
  133.          y1 += dy;
  134.          e += dey;
  135.          dey += a2;
  136.          }
  137.       if(exy<=ey || ex<ey) {
  138.          x1 += dx;
  139.          e += dex;
  140.          dex += b2;
  141.          }
  142.       (*action)(screen, x0+x1, y0+y1, f);
  143.       if(x1 == 0) {
  144.          dy = -dy;
  145.          dey = -dey + a2;
  146.          }
  147.        else if(y1 == 0) {
  148.          for(z=x1; abs(z+=dx)<=a; )
  149.             (*action)(screen, x0+z, y0+y1, f);
  150.          dx = -dx;
  151.          dex = -dex + b2;
  152.          }
  153.       } while(x1!=x2 || y1!=y2);
  154.    }
  155.  
  156. /*----------------------------------------------------------------------*/
  157.  
  158. #define sq(x) ((long)(x)*(x))
  159. #define    sgn(x)    ((x)<0? -1 : (x)==0? 0 : 1)
  160.  
  161. static long
  162. Labs(x)
  163. long x;
  164.    {
  165.    return(x<0? -x : x);
  166.    }
  167.  
  168. /*    Draw an approximate arc centered at x0,y0 of an
  169.  *    integer grid and running anti-clockwise from
  170.  *    x1,y1 to the vicinity of x2,y2.
  171.  *    If the endpoints coincide, draw a complete circle.
  172.  *
  173.  *    The "arc" is a sequence of vertically, horizontally,
  174.  *    or diagonally adjacent points that minimize 
  175.  *    abs(x^2+y^2-r^2).
  176.  *
  177.  *    The circle is guaranteed to be symmetric about
  178.  *    the horizontal, vertical, and diagonal axes
  179.  */
  180.  
  181. arc(bp, x0,y0, x2,y2, x1,y1, f)
  182. register BITMAP *bp;
  183. int x0,y0,x1,y1,x2,y2;
  184.    {
  185.    register dx, dy;
  186.    register eps;   /* x^2 + y^2 - r^2 */
  187.    int dxsq, dysq;   /* (x+dx)^2-x^2, ...*/
  188.    int ex, ey, exy;
  189.  
  190.    x1=x1-x0;
  191.    y1=y1-y0;
  192.    x2=x2-x0;
  193.    y2=y2-y0;
  194.  
  195.    nearby(x1,y1,x2,y2, &x2, &y2);
  196.  
  197.    dx = -sgn(y1);
  198.    dy = sgn(x1);
  199.    dxsq = (2*x1 + dx)*dx;
  200.    dysq = (2*y1 + dy)*dy;
  201.    eps = 0;
  202.    do {
  203.       if(x1 == 0) {
  204.          dy = -sgn(y1);
  205.          dysq = (2*y1 + dy)*dy;
  206.          }
  207.       else if(y1 == 0) {
  208.          dx = -sgn(x1);
  209.          dxsq = (2*x1 + dx)*dx;
  210.          }
  211.       ex = abs(eps + dxsq);
  212.       ey = abs(eps + dysq);
  213.       exy = abs(eps + dxsq + dysq);
  214.       if(ex<ey || exy<=ey) {
  215.          x1 += dx;
  216.          eps += dxsq;
  217.          dxsq += 2;
  218.          }
  219.       if(ey<ex || exy<=ex) {
  220.          y1 += dy;
  221.          eps += dysq;
  222.          dysq += 2;
  223.          }
  224.       bit_point(bp,x0+x1, y0+y1,f);
  225.       /* bit_blit(bp,x0+x1-1,y0+y1-1,2,2,f,NULL_DATA,0,0); */
  226.       }
  227.    while(!(x1==x2 && y1==y2));   /* Note1 */
  228.    }
  229.  
  230. /*   Note1: the equality end test is justified
  231.  *   because it is impossible that
  232.  *   abs(x^2+y^2-r^2)==abs((x+\010+-1)^2+y^2-r^2) or
  233.  *   abs(x^2+y^2-r^2)==abs(x^2+(y+\010+-1)-r^2),
  234.  *   and no values of x or y are skipped.
  235.  *
  236.  */
  237.  
  238. nearby(x1,y1, x2,y2, rx, ry)
  239. register int x1, y1, x2, y2;
  240. int *rx, *ry;
  241.    {
  242.    long eps, exy, Labs();   /*integers but many bits*/
  243.    int d, dy;
  244.    register dx;
  245.    eps = sq(x2) + sq(y2) - sq(x1) - sq(y1);
  246.    d = eps>0? -1: 1;
  247.    for( ; ; eps=exy, x2+=dx, y2+=dy) {
  248.       if(abs(y2) > abs(x2)) {
  249.          dy = d*sgn(y2);
  250.          dx = 0;
  251.          }
  252.       else {
  253.          dy = 0;
  254.          dx = d*sgn(x2);
  255.          if(dx==0)
  256.             dx = 1;
  257.          }
  258.       exy = eps + (2*x2+dx)*dx + (2*y2+dy)*dy;
  259.       if(Labs(eps) <= Labs(exy))
  260.          break;
  261.       }
  262.    *rx = x2;
  263.    *ry = y2;
  264.    return(0);
  265.    }
  266.